package com.lsj.service.impl;

import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.lsj.core.exception.CustomerException;
import com.lsj.core.response.ResponseType;
import com.lsj.core.util.JwtTokenUtil;
import com.lsj.mapper.SysUserMapper;
import com.lsj.mapper.entity.MyUserDetail;
import com.lsj.mapper.entity.SysUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;

/**
 * @Author:lin.sj
 * @Data:2021/7/6 22:11
 * @Desc: 登录类，完成登录方法token和刷新token功能
 */
@Service
public class JwtService {
    @Autowired
    AuthenticationManager authenticationManager;
    @Autowired
    JwtTokenUtil jwtTokenUtil;
    @Autowired
    SysUserMapper sysUserMapper;

    /**
     * @Author: lin.sj
     * @Date: 2021/8/18 20:37
     * @Desc: 登录接口，调用securiy的authenticationManager实现认证，认证成功返回token信息
     * 返回的token信息包括access_tooken和refresh_token，两者的差别只是时间差别，access_token用于请求数据，refresh_token用于刷新
     **/
    public JSONObject login(String username, String password) throws CustomerException{
        try {
            //组装登录用token
            UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
            //进行登录认证
            Authentication authenticate = authenticationManager.authenticate(token);
        } catch (Exception e) {
            if(e instanceof BadCredentialsException){
                throw new CustomerException(ResponseType.error,"用户或密码错误！");
            }else{
                throw new CustomerException(ResponseType.error,e.getMessage());
            }

        }
        MyUserDetail myUserDetail = getMyUser(username);
        JSONObject tokens = jwtTokenUtil.generateToken(myUserDetail);
        return tokens;
    }

    /**
     * @Author: lin.sj
     * @Date: 2021/8/18 20:38
     * @Desc: 刷新token信息，根据旧toekn信息来刷新token信息
     **/
    public JSONObject refreshToken(String token) throws CustomerException{
        Boolean expired = jwtTokenUtil.isTokenExpired(token);
        if(expired){
            throw new CustomerException(ResponseType.error,"登录已过期");
        }
        String username = jwtTokenUtil.getUsernameFromToken(token);
        MyUserDetail myUserDetail = getMyUser(username);
        JSONObject tokens = jwtTokenUtil.generateToken(myUserDetail);


        return tokens;
    }

    /**
     * @Author: lin.sj
     * @Date: 2021/8/18 20:39
     * @Desc: 从数据库加载用户信息(公用方法)
     **/
    private MyUserDetail getMyUser(String username){
        LambdaQueryWrapper<SysUser> w = new LambdaQueryWrapper<>();
        w.eq(SysUser::getUsername,username);
        SysUser sysUser = sysUserMapper.selectOne(w);
        MyUserDetail myUserDetail = Convert.convert(MyUserDetail.class, sysUser);
        return myUserDetail;
    }
}
